<?php


namespace wchat\wx;

use Exception;
use wchat\common\Result;


/**
 * Class Message
 * @package wchat\wx
 */
class Message extends SmallProgram
{

    private array $msgData = [];


    /**
     * @param string $openid
     */
    public function setOpenid(string $openid): void
    {
        $this->msgData['touser'] = $openid;
    }

    /**
     * @param string $content
     * @return Result
     * @throws
     */
    public function sendTextNews(string $content): Result
    {
        $this->msgData['msgtype'] = 'text';
        $this->msgData['text']    = ['content' => $content];

        return $this->sendKefuMsg();
    }

    /**
     * @param string $media_id
     * @return Result
     * @throws
     */
    public function sendImageNews(string $media_id): Result
    {
        $this->msgData['msgtype'] = 'image';
        $this->msgData['image']   = ['media_id' => $media_id];

        return $this->sendKefuMsg();
    }


    /**
     * @param string $media_id
     * @return Result
     * @throws
     */
    public function sendVoiceNews(string $media_id): Result
    {
        $this->msgData['msgtype'] = 'voice';
        $this->msgData['voice']   = ['media_id' => $media_id];

        return $this->sendKefuMsg();
    }

    /**
     * @param string $media_id
     * @return Result
     * @throws
     */
    public function sendMpNewsNews(string $media_id): Result
    {
        $this->msgData['msgtype'] = 'mpnews';
        $this->msgData['mpnews']  = ['media_id' => $media_id];

        return $this->sendKefuMsg();
    }


    /**
     * @param string $title
     * @param string $description
     * @param string $url
     * @param string $picurl
     * @return Result
     * @throws
     */
    public function sendNewsNews(string $title, string $description, string $url, string $picurl): Result
    {
        $this->msgData['msgtype'] = 'news';
        $this->msgData['news']    = [
            'articles' => [
                [
                    'title'       => $title,
                    'description' => $description,
                    'url'         => $url,
                    'picurl'      => $picurl
                ]
            ]
        ];
        return $this->sendKefuMsg();
    }


    /**
     * @param string $title
     * @return Result
     * @throws
     */
    public function sendCardNews(string $title): Result
    {
        $this->msgData['msgtype'] = 'wxcard';
        $this->msgData['wxcard']  = ['card_id' => $title];

        return $this->sendKefuMsg();
    }


    /**
     * @param string $media_id
     * @param string $thumb_media_id
     * @param string $title
     * @param string $description
     * @return Result
     * @throws
     */
    public function sendVideoNews(string $media_id, string $thumb_media_id, string $title, string $description): Result
    {
        $this->msgData['msgtype'] = 'video';
        $this->msgData['video']   = [
            'media_id' => [
                'media_id'       => $media_id,
                'thumb_media_id' => $thumb_media_id,
                'title'          => $title,
                'description'    => $description
            ]
        ];
        return $this->sendKefuMsg();
    }


    /**
     * @param string $musicurl
     * @param string $hqmusicurl
     * @param string $thumb_media_id
     * @param string $title
     * @param string $description
     * @return Result
     * @throws
     */
    public function sendMusicNews(string $musicurl, string $hqmusicurl, string $thumb_media_id, string $title, string $description): Result
    {
        $this->msgData['msgtype'] = 'music';
        $this->msgData['music']   = [
            'title'          => $title,
            'description'    => $description,
            'musicurl'       => $musicurl,
            'hqmusicurl'     => $hqmusicurl,
            'thumb_media_id' => $thumb_media_id
        ];
        return $this->sendKefuMsg();
    }


    /**
     * @param string $head_content
     * @param string $tail_content
     * @param array $menus
     * @return Result
     * @throws
     */
    public function sendMenuNews(string $head_content, string $tail_content, array $menus = []): Result
    {
        $this->msgData['msgtype'] = 'msgmenu';
        $this->msgData['msgmenu'] = [
            'head_content' => $head_content,
            'tail_content' => $tail_content,
        ];
        if (empty($menus) || !is_array($menus) || count($menus) < 2) {
            throw new Exception('菜单选项必须有2个');
        }
        foreach ($menus as $val) {
            $this->addNewsMenu($val['id'], $val['name']);
        }
        return $this->sendKefuMsg();
    }

    private int $index = 0;

    /**
     * @param string $id
     * @param string $menuName
     * @return $this
     */
    public function addNewsMenu(string $id, string $menuName): static
    {
        $lists['id']                                    = $id;
        $lists['content']                               = $menuName;
        $this->msgData['msgmenu']['list'][$this->index] = $lists;
        ++$this->index;
        return $this;
    }

    /**
     * @param string $title
     * @param string $appid
     * @param string $pagepath
     * @param string $thumb_media_id
     * @return Result
     * @throws
     */
    public function sendMiniprogrampageNews(string $title, string $appid, string $pagepath, string $thumb_media_id): Result
    {
        $this->msgData['msgtype']         = 'msgmenu';
        $this->msgData['miniprogrampage'] = [
            'title'          => $title,
            'appid'          => $appid,
            'pagepath'       => $pagepath,
            'thumb_media_id' => $thumb_media_id,
        ];
        return $this->sendKefuMsg();
    }

    /**
     * @param string $filePath
     * @param string $type
     * @param bool $isPermanent
     * @param string $title
     * @param string $introduction
     * @return mixed
     * @throws
     */
    public function uploadFile(string $filePath, string $type, bool $isPermanent = false, string $title = '', string $introduction = ''): Result
    {
        if (!file_exists($filePath)) {
            throw new Exception('文件不存在');
        }
        if (!in_array($type, ['image', 'voice', 'video', 'thumb'])) {
            throw new Exception('暂不支持的文件类型');
        }
        $token = $this->payConfig->getAccessToken();
        if ($isPermanent) {
            $url = "/cgi-bin/material/add_material?access_token={$token}&type={$type}";
        } else {
            $url = "/cgi-bin/media/upload?access_token={$token}&type={$type}";
        }
        $mime      = mime_content_type($filePath);
        $real_path = new \CURLFile(realpath($filePath));
        $data      = ["media" => $real_path, 'form-data[filename]' => $filePath, 'form-data[Content-Type]' => $mime];
        if ($isPermanent && $mime == 'video/mp3') {
            $data = ['media' => $real_path, 'description[title]' => $title, 'description[introduction]' => $introduction];
        }
        return $this->post('api.weixin.qq.com', $url, $data);
    }


    /**
     * @return array
     */
    public function getContents(): array
    {
        return $this->msgData;
    }


    /**
     * @return Result
     * @throws
     */
    private function sendKefuMsg(): Result
    {
        $url = '/cgi-bin/message/custom/send?access_token=' . $this->payConfig->getAccessToken();
        return $this->post('api.weixin.qq.com', $url, $this->msgData);
    }
}
